home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / raid / devRaidInitiate.c < prev    next >
C/C++ Source or Header  |  1991-06-27  |  38KB  |  1,222 lines

  1. /* 
  2.  * devRaidInitiate.c --
  3.  *
  4.  *    This file implements the BlockDevice interface for homogeneous disk
  5.  *    arrays.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * All rights reserved.
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "sync.h"
  21. #include "sprite.h"
  22. #include "fs.h"
  23. #include "dev.h"
  24. #include "devBlockDevice.h"
  25. #include "devRaid.h"
  26. #include "semaphore.h"
  27. #include "stdlib.h"
  28. #include "devRaidUtil.h"
  29. #include "schedule.h"
  30. #include "devRaidProto.h"
  31.  
  32.  
  33. /*
  34.  *----------------------------------------------------------------------
  35.  *
  36.  * Raid_InitiateIORequests --
  37.  *
  38.  *    Initiates IO requests specified by reqControlPtr.
  39.  *    Calls doneProc with clientData, the number of requests that have
  40.  *    failed and a pointer to the last failed request when the IO is complete.
  41.  *
  42.  * Results:
  43.  *    None.
  44.  *
  45.  * Side effects:
  46.  *    The IO operations.
  47.  *
  48.  *----------------------------------------------------------------------
  49.  */
  50.  
  51. void blockIODoneProc();
  52. void nonInterruptLevelCallBackProc();
  53.  
  54. void 
  55. Raid_InitiateIORequests(reqControlPtr, doneProc, clientData)
  56.     RaidRequestControl    *reqControlPtr;
  57.     void           (*doneProc)();
  58.     ClientData         clientData;
  59. {
  60.     RaidIOControl    *IOControlPtr;
  61.     RaidBlockRequest    *reqPtr;
  62.     int             i;
  63.  
  64.     /*
  65.      * Initiate IO's.
  66.      */
  67.     IOControlPtr = Raid_MakeIOControl(doneProc, clientData);
  68.     IOControlPtr->numIO++;
  69.     for ( i = 0; i < reqControlPtr->numReq; i++ ) {
  70.     reqPtr = &reqControlPtr->reqPtr[i];
  71.     if (reqPtr->state == REQ_READY) {
  72.         reqPtr->state = REQ_PENDING;
  73.         MASTER_LOCK(&IOControlPtr->mutex);
  74.         IOControlPtr->numIO++;
  75.         MASTER_UNLOCK(&IOControlPtr->mutex);
  76.         reqPtr->devReq.doneProc   = blockIODoneProc;
  77.         reqPtr->devReq.clientData = (ClientData) IOControlPtr;
  78.         (void) Dev_BlockDeviceIO(
  79.             reqPtr->raidPtr->disk[reqPtr->col][reqPtr->row]->handlePtr,
  80.             (DevBlockDeviceRequest *) reqPtr);
  81.     }
  82.     }
  83.  
  84.     MASTER_LOCK(&IOControlPtr->mutex);
  85.     IOControlPtr->numIO--;
  86.     if (IOControlPtr->numIO == 0) {
  87.         MASTER_UNLOCK(&IOControlPtr->mutex);
  88.         IOControlPtr->doneProc(IOControlPtr->clientData,
  89.         IOControlPtr->numFailed, IOControlPtr->failedReqPtr);
  90.     Raid_FreeIOControl(IOControlPtr);
  91.     } else {
  92.         MASTER_UNLOCK(&IOControlPtr->mutex);
  93.     }
  94. }
  95.  
  96.  
  97. /*
  98.  *----------------------------------------------------------------------
  99.  *
  100.  * blockIODoneProc --
  101.  *
  102.  *    Callback procedure for Raid_InitiateIORequests.
  103.  *    This procedure is called once each time an individual IO reqeust
  104.  *    completes.
  105.  *
  106.  * Results:
  107.  *    None.
  108.  *
  109.  * Side effects:
  110.  *    Reports errors.
  111.  *
  112.  *----------------------------------------------------------------------
  113.  */
  114.  
  115. void
  116. blockIODoneProc(reqPtr, status, amountTransferred)
  117.     RaidBlockRequest    *reqPtr;
  118.     ReturnStatus     status;
  119.     int             amountTransferred;
  120. {
  121.     RaidIOControl    *IOControlPtr;
  122.     IOControlPtr = (RaidIOControl *) reqPtr->devReq.clientData;
  123.  
  124.     /*
  125.      * Check to see if disk has failed since request was initiated.
  126.      */
  127.     if (!IsValid(reqPtr->diskPtr,
  128.         ByteToSector(reqPtr->raidPtr, reqPtr->devReq.startAddress),
  129.         ByteToSector(reqPtr->raidPtr, reqPtr->devReq.bufferLen))) {
  130.     status = FAILURE;
  131.     }
  132.  
  133.     reqPtr->status = status;
  134.     if (status != SUCCESS) {
  135.         reqPtr->state = REQ_FAILED;
  136.     Raid_ReportRequestError(reqPtr);
  137.     if (reqPtr->devReq.operation == FS_WRITE) {
  138.         Raid_FailDisk(reqPtr->raidPtr,
  139.             reqPtr->col, reqPtr->row, reqPtr->version);
  140.     }
  141.     } else {
  142.         reqPtr->state = REQ_COMPLETED;
  143.     }
  144.  
  145.     MASTER_LOCK(&IOControlPtr->mutex);
  146.     IOControlPtr->amountTransferred += amountTransferred;
  147.  
  148.     /*
  149.      * A Raid IO operation fails if any of the component operations fail.
  150.      * Therefore, don't overwrite status if a previous operation has failed.
  151.      */
  152.     if (status != SUCCESS) {
  153.         IOControlPtr->numFailed++;
  154.         IOControlPtr->failedReqPtr = reqPtr;
  155.     }
  156.  
  157.     /*
  158.      * Check if all component IO's done.
  159.      */
  160.     IOControlPtr->numIO--;
  161.     if (IOControlPtr->numIO == 0) {
  162.         MASTER_UNLOCK(&IOControlPtr->mutex);
  163.     /*
  164.      * this forces the call-back to happen at non-interrupt level
  165.      */
  166.     Proc_CallFunc(nonInterruptLevelCallBackProc,(ClientData)IOControlPtr,0);
  167.     } else {
  168.         MASTER_UNLOCK(&IOControlPtr->mutex);
  169.     }
  170. }
  171.  
  172.  
  173. /*
  174.  *----------------------------------------------------------------------
  175.  *
  176.  * nonInterruptLevelCallBackProc --
  177.  *
  178.  *    None-interrupt level callback procedure for Raid_InitiateIORequests.
  179.  *
  180.  * Results:
  181.  *    None.
  182.  *
  183.  * Side effects:
  184.  *
  185.  *----------------------------------------------------------------------
  186.  */
  187.  
  188. void
  189. nonInterruptLevelCallBackProc(IOControlPtr)
  190.     RaidIOControl    *IOControlPtr;
  191. {
  192.     IOControlPtr->doneProc(IOControlPtr->clientData,
  193.         IOControlPtr->numFailed, IOControlPtr->failedReqPtr);
  194.     Raid_FreeIOControl(IOControlPtr);
  195. }
  196.  
  197.  
  198. /*
  199.  *----------------------------------------------------------------------
  200.  *
  201.  * InitiateStripeIOFailure --
  202.  *
  203.  *    Causes the IO operation to fail, presumably because it can not
  204.  *    be completely (i.e. more than one disk in a group has failed.)
  205.  *
  206.  * Results:
  207.  *    None.
  208.  *
  209.  * Side effects:
  210.  *    None.
  211.  *
  212.  *----------------------------------------------------------------------
  213.  */
  214.  
  215. static void stripeIODoneProc();
  216.  
  217. static void
  218. InitiateStripeIOFailure(stripeIOControlPtr)
  219.     RaidStripeIOControl    *stripeIOControlPtr;
  220. {
  221.     stripeIODoneProc(stripeIOControlPtr, 2);
  222. }
  223.  
  224.  
  225. /*
  226.  *----------------------------------------------------------------------
  227.  *
  228.  * InitiateStripeWrite --
  229.  *
  230.  *    Initiates a stripe write (i.e. an IO that does not span stripe
  231.  *    boundaries) via either Raid_InitiateIORequests, InitiateReconstructWrite
  232.  *    or InitiateReadModifyWrite.
  233.  *    Sets up the recovery procedure if recovery is possible.  Note that
  234.  *    the recovery procedure for InitiateReconstructWrite is
  235.  *    InitiateReadModifyWrite and visa versa.
  236.  *    Calls callback procedure specified by stripeIOControlPtr with
  237.  *    stripeIOControlPtr, number of requests that have failed and a
  238.  *    pointer to the last failed request, when the IO is complete.
  239.  *
  240.  * Results:
  241.  *    None.
  242.  *
  243.  * Side effects:
  244.  *    The IO operation.
  245.  *
  246.  *----------------------------------------------------------------------
  247.  */
  248.  
  249. static void InitiateSplitStripeWrite();
  250. static void InitiateReadModifyWrite();
  251. static void InitiateReconstructWrite();
  252. static void oldInfoReadDoneProc();
  253. static void stripeWriteDoneProc();
  254.  
  255. static void
  256. InitiateStripeWrite(stripeIOControlPtr)
  257.     RaidStripeIOControl    *stripeIOControlPtr;
  258. {
  259.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  260.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  261.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  262.     Address         buffer        = stripeIOControlPtr->buffer;
  263.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  264.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  265.     char        *parityBuf     = stripeIOControlPtr->parityBuf;
  266.  
  267.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  268.     AddRaidParityRequest(reqControlPtr, raidPtr, FS_READ,
  269.         firstSector, parityBuf, ctrlData);
  270.     /*
  271.      * Check to see if parity disk has failed.
  272.      */
  273.     if (reqControlPtr->numFailed > 0) {
  274.     /*
  275.      * If parity disk has failed, just write the data.
  276.      */
  277.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  278.     AddRaidDataRequests(reqControlPtr, raidPtr, FS_WRITE,
  279.         firstSector, nthSector, buffer, ctrlData);
  280.     if (reqControlPtr->numFailed == 0) {
  281.         Raid_InitiateIORequests(stripeIOControlPtr->reqControlPtr,
  282.             stripeIODoneProc, (ClientData) stripeIOControlPtr);
  283.     } else {
  284.         InitiateStripeIOFailure(stripeIOControlPtr);
  285.     }
  286.     } else if (raidPtr->dataSectorsPerStripe/(nthSector-firstSector) > 2) {
  287.     /*
  288.      * If less than half of the stripe is being written, do a
  289.      * read modify write.
  290.      */
  291.     stripeIOControlPtr->recoverProc = InitiateReconstructWrite;
  292.     InitiateReadModifyWrite(stripeIOControlPtr);
  293.     } else {
  294.     /*
  295.      * If half or more of the stripe is being written, do a
  296.      * reconstruct write.
  297.      */
  298.     stripeIOControlPtr->recoverProc = InitiateReadModifyWrite;
  299.     InitiateReconstructWrite(stripeIOControlPtr);
  300.     }
  301. }
  302.  
  303.  
  304. /*
  305.  *----------------------------------------------------------------------
  306.  *
  307.  * InitiateSplitStripeWrite --
  308.  *
  309.  *    If a write request which covers multiple stripe units fails durring
  310.  *    the read phase and the failed component is not a full stripe unit,
  311.  *    It is necessary to do both a read-modify-write and a reconstruct write
  312.  *    in order to complete the entire request.
  313.  *    Note: StripeIOControlPtr->failedReqPtr is assumed to point to the data
  314.  *    part of the failed request.
  315.  *
  316.  * Results:
  317.  *    None.
  318.  *
  319.  * Side effects:
  320.  *    The IO operation.
  321.  *
  322.  *----------------------------------------------------------------------
  323.  */
  324.  
  325. static void
  326. InitiateSplitStripeWrite(stripeIOControlPtr)
  327.     RaidStripeIOControl    *stripeIOControlPtr;
  328. {
  329.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  330.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  331.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  332. /*    Address         buffer        = stripeIOControlPtr->buffer; */
  333.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  334.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  335.     char        *parityBuf     = stripeIOControlPtr->parityBuf;
  336.     char        *readBuf       = stripeIOControlPtr->readBuf;
  337.     int             failedAddr    = (int)
  338.            stripeIOControlPtr->reqControlPtr->failedReqPtr->devReq.startAddress;
  339.     int             failedLen     =
  340.            stripeIOControlPtr->reqControlPtr->failedReqPtr->devReq.bufferLen;
  341.     int             rangeOff;
  342.     int             rangeLen;
  343.  
  344.     /*
  345.      * 'Deduce' data part of failed request.
  346.      */
  347.     if (stripeIOControlPtr->recoverProc == (void(*)())InitiateReadModifyWrite) {
  348.     if (StripeUnitOffset(raidPtr, failedAddr) == 0) {
  349.         failedAddr = failedAddr + failedLen;
  350.         failedLen = raidPtr->bytesPerStripeUnit - failedLen;
  351.     } else {
  352.         failedAddr = failedAddr - StripeUnitOffset(raidPtr, failedAddr);
  353.         failedLen = raidPtr->bytesPerStripeUnit - failedLen;
  354.     }
  355.     }
  356.     if (StripeUnitOffset(raidPtr, failedAddr) == 0) {
  357.     rangeOff = failedLen;
  358.     rangeLen = raidPtr->bytesPerStripeUnit -
  359.         StripeUnitOffset(raidPtr, rangeOff);
  360.     } else {
  361.     rangeOff = 0;
  362.     rangeLen = StripeUnitOffset(raidPtr, failedAddr);
  363.     }
  364.     stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  365.     stripeIOControlPtr->rangeOff = 0;
  366.     stripeIOControlPtr->rangeLen = raidPtr->bytesPerStripeUnit;
  367.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  368.     /*
  369.      * reconstructWrite strip
  370.      */
  371.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  372.         FirstSectorOfStripe(raidPtr, firstSector), firstSector,
  373.         readBuf, ctrlData,
  374.         failedAddr, failedLen);
  375.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  376.         nthSector, NthSectorOfStripe(raidPtr, firstSector),
  377.         readBuf + SectorToByte(raidPtr,
  378.                 firstSector - FirstSectorOfStripe(raidPtr, firstSector)),
  379.         ctrlData, failedAddr, failedLen);
  380.     /*
  381.      * RMW strip
  382.      */
  383.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  384.         firstSector, nthSector, readBuf + SectorToByte(raidPtr,
  385.             raidPtr->dataSectorsPerStripe - (nthSector-firstSector)),
  386.         ctrlData, rangeOff, rangeLen);
  387.     Raid_AddParityRangeRequest(reqControlPtr, raidPtr, FS_READ,
  388.         firstSector, parityBuf, ctrlData,
  389.         rangeOff, rangeLen);
  390.     if (reqControlPtr->numFailed == 0) {
  391.     Raid_InitiateIORequests(reqControlPtr,
  392.         oldInfoReadDoneProc, (ClientData) stripeIOControlPtr);
  393.     } else {
  394.     stripeIOControlPtr->recoverProc(stripeIOControlPtr);
  395.     }
  396. }
  397.  
  398.  
  399. /*
  400.  *----------------------------------------------------------------------
  401.  *
  402.  * InitiateReadModifyWrite --
  403.  *
  404.  *    Initiates a read modify write.  (i.e. read old data and old parity,
  405.  *    computes the new parity and then writes the new data and new parity)
  406.  *    Calls the recovery procedure if a read modify wirte can not complete.
  407.  *    Calls callback procedure specified by stripeIOControlPtr with
  408.  *    stripeIOControlPtr, number of requests that have failed and a
  409.  *    pointer to the last failed request, when the IO is complete.
  410.  *
  411.  * Results:
  412.  *    None.
  413.  *
  414.  * Side effects:
  415.  *    The IO operation.
  416.  *
  417.  *----------------------------------------------------------------------
  418.  */
  419.  
  420. static void
  421. InitiateReadModifyWrite(stripeIOControlPtr)
  422.     RaidStripeIOControl    *stripeIOControlPtr;
  423. {
  424.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  425.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  426.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  427. /*    Address         buffer        = stripeIOControlPtr->buffer; */
  428.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  429.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  430.     char        *parityBuf     = stripeIOControlPtr->parityBuf;
  431.     char        *readBuf       = stripeIOControlPtr->readBuf;
  432.     void           (*recoverProc)()= stripeIOControlPtr->recoverProc;
  433.  
  434.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  435.     AddRaidDataRequests(reqControlPtr, raidPtr, FS_READ,
  436.         firstSector, nthSector, readBuf, ctrlData);
  437.     if (reqControlPtr->numReq == 1) {
  438.     stripeIOControlPtr->rangeOff =
  439.         reqControlPtr->reqPtr[0].devReq.startAddress;
  440.     stripeIOControlPtr->rangeLen =
  441.         reqControlPtr->reqPtr[0].devReq.bufferLen;
  442.     } else {
  443.     stripeIOControlPtr->rangeOff = 0;
  444.     stripeIOControlPtr->rangeLen = raidPtr->bytesPerStripeUnit;
  445.     }
  446.     Raid_AddParityRangeRequest(reqControlPtr, raidPtr, FS_READ,
  447.         firstSector, parityBuf, ctrlData,
  448.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  449.     if (reqControlPtr->numFailed == 0) {
  450.     Raid_InitiateIORequests(reqControlPtr,
  451.         oldInfoReadDoneProc, (ClientData) stripeIOControlPtr);
  452.     } else {
  453.     /*
  454.      * If the request covers multiple stripe units and is not stripe unit
  455.      * aligned, check to see if the failed request is a partial
  456.      * stripe unit.  If it is, then both a read-modify-write and
  457.      * a reconstruct write is necessary to complete the request.
  458.      */
  459.     DevBlockDeviceRequest *devReqPtr = &reqControlPtr->failedReqPtr->devReq;
  460.     if (stripeIOControlPtr->rangeLen == raidPtr->bytesPerStripeUnit &&
  461.         devReqPtr->bufferLen != raidPtr->bytesPerStripeUnit &&
  462.         recoverProc != (void (*)()) InitiateStripeIOFailure) {
  463.         stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  464.         InitiateSplitStripeWrite(stripeIOControlPtr);
  465.     } else {
  466.         stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  467.         recoverProc(stripeIOControlPtr);
  468.     }
  469.     }
  470. }
  471.  
  472.  
  473. /*
  474.  *----------------------------------------------------------------------
  475.  *
  476.  * InitiateReconstructWrite --
  477.  *
  478.  *    Initiates a reconstruct write.  (i.e. read rest of stripe if any
  479.  *    computes the new parity and then writes the new data and new parity)
  480.  *    Calls the recovery procedure if a read modify wirte can not complete.
  481.  *    Calls callback procedure specified by stripeIOControlPtr with
  482.  *    stripeIOControlPtr, number of requests that have failed and a
  483.  *    pointer to the last failed request, when the IO is complete.
  484.  *
  485.  * Results:
  486.  *    None.
  487.  *
  488.  * Side effects:
  489.  *    The IO operation.
  490.  *
  491.  *----------------------------------------------------------------------
  492.  */
  493.  
  494. static void
  495. InitiateReconstructWrite(stripeIOControlPtr)
  496.     RaidStripeIOControl    *stripeIOControlPtr;
  497. {
  498.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  499.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  500.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  501. /*    Address         buffer        = stripeIOControlPtr->buffer; */
  502.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  503.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  504. /*    char        *parityBuf     = stripeIOControlPtr->parityBuf; */
  505.     char        *readBuf       = stripeIOControlPtr->readBuf;
  506.     void           (*recoverProc)()= stripeIOControlPtr->recoverProc;
  507.  
  508.     /*
  509.      * If writing only one stripe unit, range restrict the write.
  510.      */
  511.     if (SectorToStripeUnitID(raidPtr, firstSector) ==
  512.         SectorToStripeUnitID(raidPtr, nthSector-1)) {
  513.     stripeIOControlPtr->rangeOff = SectorToByte(raidPtr, firstSector);
  514.         stripeIOControlPtr->rangeLen =
  515.         SectorToByte(raidPtr, nthSector-firstSector);
  516.     } else {
  517.     stripeIOControlPtr->rangeOff = 0;
  518.     stripeIOControlPtr->rangeLen = raidPtr->bytesPerStripeUnit;
  519.     }
  520.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  521.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  522.         FirstSectorOfStripe(raidPtr, firstSector), firstSector,
  523.         readBuf, ctrlData,
  524.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  525.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  526.         nthSector, NthSectorOfStripe(raidPtr, firstSector),
  527.         readBuf + SectorToByte(raidPtr,
  528.                 firstSector - FirstSectorOfStripe(raidPtr, firstSector)),
  529.         ctrlData,stripeIOControlPtr->rangeOff,stripeIOControlPtr->rangeLen);
  530.     if (reqControlPtr->numFailed == 0) {
  531.     Raid_InitiateIORequests(stripeIOControlPtr->reqControlPtr,
  532.         oldInfoReadDoneProc, (ClientData) stripeIOControlPtr);
  533.     } else {
  534.     /*
  535.      * If the request covers multiple stripe units and is not stripe unit
  536.      * aligned, check to see if the failed request is a partial
  537.      * stripe unit.  If it is, then both a read-modify-write and
  538.      * a reconstruct write is necessary to complete the request.
  539.      */
  540.     DevBlockDeviceRequest *devReqPtr = &reqControlPtr->failedReqPtr->devReq;
  541.     if (stripeIOControlPtr->rangeLen == raidPtr->bytesPerStripeUnit &&
  542.         devReqPtr->bufferLen != raidPtr->bytesPerStripeUnit &&
  543.         recoverProc != (void(*)()) InitiateStripeIOFailure) {
  544.         InitiateSplitStripeWrite(stripeIOControlPtr);
  545.     } else {
  546.         stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  547.         recoverProc(stripeIOControlPtr);
  548.     }
  549.     }
  550. }
  551.  
  552.  
  553. /*
  554.  *----------------------------------------------------------------------
  555.  *
  556.  * oldInfoReadDoneProc --
  557.  *
  558.  *    Callback procedure for InitiateReadModifyWrite and
  559.  *    InitiateReconstructWrite.
  560.  *    This procedure is called after the old data and parity have been read
  561.  *    in the process of writing new data.
  562.  *    If an error has occured, the recovery procedure is called.
  563.  *
  564.  * Results:
  565.  *    None.
  566.  *
  567.  * Side effects:
  568.  *    IO operations.
  569.  *
  570.  *----------------------------------------------------------------------
  571.  */
  572.  
  573. static void
  574. oldInfoReadDoneProc(stripeIOControlPtr, numFailed, failedReqPtr)
  575.     RaidStripeIOControl    *stripeIOControlPtr;
  576.     int              numFailed;
  577.     RaidBlockRequest    *failedReqPtr;
  578. {
  579.     Raid    *raidPtr = stripeIOControlPtr->raidPtr;
  580.  
  581.     if (numFailed == 0) {
  582.     char            *parityBuf;
  583.  
  584. #ifndef NODATA
  585.         parityBuf = Malloc((unsigned) raidPtr->bytesPerStripeUnit);
  586.     bzero(parityBuf, raidPtr->bytesPerStripeUnit);
  587. #endif
  588.  
  589.     Raid_XorRangeRequests(stripeIOControlPtr->reqControlPtr,
  590.         raidPtr, parityBuf,
  591.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  592.         stripeIOControlPtr->reqControlPtr->numReq = 0;
  593.         stripeIOControlPtr->reqControlPtr->numFailed = 0;
  594.         Raid_AddDataRangeRequests(stripeIOControlPtr->reqControlPtr,
  595.         raidPtr, FS_WRITE,
  596.         stripeIOControlPtr->firstSector, stripeIOControlPtr->nthSector,
  597.                 stripeIOControlPtr->buffer, stripeIOControlPtr->ctrlData,
  598.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  599.     Raid_XorRangeRequests(stripeIOControlPtr->reqControlPtr,
  600.         raidPtr, parityBuf,
  601.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  602. #ifndef NODATA
  603.     Free(stripeIOControlPtr->parityBuf);
  604. #endif
  605.     stripeIOControlPtr->parityBuf = parityBuf;
  606.         Raid_AddParityRangeRequest(stripeIOControlPtr->reqControlPtr,
  607.         raidPtr, FS_WRITE,
  608.             stripeIOControlPtr->firstSector, stripeIOControlPtr->parityBuf,
  609.         stripeIOControlPtr->ctrlData,
  610.         stripeIOControlPtr->rangeOff, stripeIOControlPtr->rangeLen);
  611.     switch (stripeIOControlPtr->reqControlPtr->numFailed) {
  612.     case 0:
  613.             Raid_InitiateIORequests(stripeIOControlPtr->reqControlPtr,
  614.             stripeWriteDoneProc, (ClientData) stripeIOControlPtr);
  615.         break;
  616.     case 1:
  617.             Raid_InitiateIORequests(stripeIOControlPtr->reqControlPtr,
  618.             stripeIODoneProc, (ClientData) stripeIOControlPtr);
  619.         break;
  620.     default:
  621.         InitiateStripeIOFailure(stripeIOControlPtr);
  622.         break;
  623.     }
  624.     } else {
  625.         void       (*recoverProc)() = stripeIOControlPtr->recoverProc;
  626.     stripeIOControlPtr->reqControlPtr->failedReqPtr = failedReqPtr;
  627.     /*
  628.      * If the request covers multiple stripe units and is not stripe unit
  629.      * aligned, check to see if the failed request is a partial
  630.      * stripe unit.  If it is, then both a read-modify-write and
  631.      * a reconstruct write is necessary to complete the request.
  632.      */
  633.     if (stripeIOControlPtr->rangeLen == raidPtr->bytesPerStripeUnit &&
  634.         failedReqPtr->devReq.bufferLen != raidPtr->bytesPerStripeUnit &&
  635.         recoverProc != (void (*)()) InitiateStripeIOFailure) {
  636.         InitiateSplitStripeWrite(stripeIOControlPtr);
  637.     } else {
  638.         stripeIOControlPtr->recoverProc = InitiateStripeIOFailure;
  639.         recoverProc(stripeIOControlPtr);
  640.     }
  641.     }
  642. }
  643.  
  644.  
  645. /*
  646.  *----------------------------------------------------------------------
  647.  *
  648.  * stripeWriteDoneProc --
  649.  *
  650.  *    Callback procedure for oldInfoReadDoneProc.
  651.  *    This procedure is called after the new data and parity have
  652.  *    been written.
  653.  *    Since one of the writes is redundant, the IO is considered to have
  654.  *    succeeded as long as the number of failures is less than or equal
  655.  *    to one.
  656.  *
  657.  * Results:
  658.  *    None.
  659.  *
  660.  * Side effects:
  661.  *    None.
  662.  *
  663.  *----------------------------------------------------------------------
  664.  */
  665.  
  666. static void
  667. stripeWriteDoneProc(stripeIOControlPtr, numFailed)
  668.     RaidStripeIOControl    *stripeIOControlPtr;
  669.     int             numFailed;
  670. {
  671.     if (numFailed <= 1) {
  672.     stripeIODoneProc(stripeIOControlPtr, 0);
  673.     } else {
  674.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  675.     }
  676. }
  677.  
  678.  
  679. /*
  680.  *----------------------------------------------------------------------
  681.  *
  682.  * InitiateStripeRead --
  683.  *
  684.  *    Initiates a stripe read (i.e. an IO that does not span stripe
  685.  *    boundaries).
  686.  *    Calls callback procedure specified by stripeIOControlPtr with
  687.  *    stripeIOControlPtr, number of requests that have failed and a
  688.  *    pointer to the last failed request, when the IO is complete.
  689.  *
  690.  * Results:
  691.  *    None.
  692.  *
  693.  * Side effects:
  694.  *    The IO operation.
  695.  *
  696.  *----------------------------------------------------------------------
  697.  */
  698.  
  699. static void stripeReadDoneProc();
  700. static void reconstructStripeReadDoneProc();
  701. static void InitiateReconstructRead();
  702.  
  703. static void
  704. InitiateStripeRead(stripeIOControlPtr)
  705.     RaidStripeIOControl    *stripeIOControlPtr;
  706. {
  707.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  708.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  709.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  710.     Address         buffer        = stripeIOControlPtr->buffer;
  711.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  712.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  713. /*    char        *parityBuf     = stripeIOControlPtr->parityBuf; */
  714. /*    char        *readBuf       = stripeIOControlPtr->readBuf; */
  715.  
  716.     reqControlPtr->numReq = reqControlPtr->numFailed = 0;
  717.     AddRaidDataRequests(reqControlPtr, raidPtr, FS_READ,
  718.         firstSector, nthSector, buffer, ctrlData);
  719.     switch (reqControlPtr->numFailed) {
  720.     case 0:
  721.         Raid_InitiateIORequests(reqControlPtr,
  722.         stripeReadDoneProc, (ClientData) stripeIOControlPtr);
  723.     break;
  724.     case 1:
  725.     InitiateReconstructRead(stripeIOControlPtr);
  726.     break;
  727.     default:
  728.     InitiateStripeIOFailure(stripeIOControlPtr);
  729.     break;
  730.     }
  731. }
  732.  
  733.  
  734. /*
  735.  *----------------------------------------------------------------------
  736.  *
  737.  * stripeReadDoneProc --
  738.  *
  739.  *    Callback procedure for InitiateStripeRead.
  740.  *
  741.  * Results:
  742.  *    None.
  743.  *
  744.  * Side effects:
  745.  *    None.
  746.  *
  747.  *----------------------------------------------------------------------
  748.  */
  749.  
  750. static void
  751. stripeReadDoneProc(stripeIOControlPtr, numFailed, failedReqPtr)
  752.     RaidStripeIOControl    *stripeIOControlPtr;
  753.     int             numFailed;
  754.     RaidBlockRequest    *failedReqPtr;
  755. {
  756.     switch (numFailed) {
  757.     case 0:
  758.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  759.     break;
  760.     case 1:
  761.     stripeIOControlPtr->reqControlPtr->failedReqPtr = failedReqPtr;
  762.     InitiateReconstructRead(stripeIOControlPtr);
  763.     break;
  764.     default:
  765.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  766.     break;
  767.     }
  768. }
  769.  
  770.  
  771. /*
  772.  *----------------------------------------------------------------------
  773.  *
  774.  * InitiateReconstructRead --
  775.  *
  776.  *    Initiates a reconstruct read (i.e. computes requested data by reading
  777.  *    the rest of the stripe and parity).
  778.  *    Calls callback procedure specified by stripeIOControlPtr with
  779.  *    stripeIOControlPtr, number of requests that have failed and a
  780.  *    pointer to the last failed request, when the IO is complete.
  781.  *
  782.  * Results:
  783.  *    None.
  784.  *
  785.  * Side effects:
  786.  *    The IO operation.
  787.  *
  788.  *----------------------------------------------------------------------
  789.  */
  790.  
  791. static void
  792. InitiateReconstructRead(stripeIOControlPtr)
  793.     RaidStripeIOControl    *stripeIOControlPtr;
  794. {
  795.     Raid        *raidPtr       = stripeIOControlPtr->raidPtr;
  796.     unsigned         firstSector   = stripeIOControlPtr->firstSector;
  797.     unsigned         nthSector     = stripeIOControlPtr->nthSector;
  798. /*    Address         buffer        = stripeIOControlPtr->buffer; */
  799.     int             ctrlData      = stripeIOControlPtr->ctrlData;
  800.     RaidRequestControl    *reqControlPtr = stripeIOControlPtr->reqControlPtr;
  801.     char        *parityBuf     = stripeIOControlPtr->parityBuf;
  802.     char        *readBuf       = stripeIOControlPtr->readBuf;
  803.  
  804.     reqControlPtr->numFailed = 0;
  805.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  806.         FirstSectorOfStripe(raidPtr, firstSector), firstSector,
  807.         readBuf, ctrlData,
  808.         (int) reqControlPtr->failedReqPtr->devReq.startAddress,
  809.         reqControlPtr->failedReqPtr->devReq.bufferLen);
  810.     Raid_AddDataRangeRequests(reqControlPtr, raidPtr, FS_READ,
  811.         nthSector, NthSectorOfStripe(raidPtr, firstSector),
  812.         readBuf + SectorToByte(raidPtr,
  813.             firstSector - FirstSectorOfStripe(raidPtr, firstSector)),
  814.         ctrlData,
  815.         (int) reqControlPtr->failedReqPtr->devReq.startAddress,
  816.         reqControlPtr->failedReqPtr->devReq.bufferLen);
  817.     Raid_AddParityRangeRequest(reqControlPtr, raidPtr, FS_READ,
  818.         firstSector, parityBuf, ctrlData,
  819.         (int) reqControlPtr->failedReqPtr->devReq.startAddress,
  820.         reqControlPtr->failedReqPtr->devReq.bufferLen);
  821.     switch (reqControlPtr->numFailed) {
  822.     case 0:
  823.     Raid_InitiateIORequests(stripeIOControlPtr->reqControlPtr,
  824.         reconstructStripeReadDoneProc, (ClientData) stripeIOControlPtr);
  825.     break;
  826.     default:
  827.     InitiateStripeIOFailure(stripeIOControlPtr);
  828.     break;
  829.     }
  830. }
  831.  
  832.  
  833. /*
  834.  *----------------------------------------------------------------------
  835.  *
  836.  * reconstructStripeReadDoneProc --
  837.  *
  838.  *    Callback procedure for InitiateReconstructRead.
  839.  *
  840.  * Results:
  841.  *    None.
  842.  *
  843.  * Side effects:
  844.  *    None.
  845.  *
  846.  *----------------------------------------------------------------------
  847.  */
  848.  
  849. static void
  850. reconstructStripeReadDoneProc(stripeIOControlPtr, numFailed)
  851.     RaidStripeIOControl    *stripeIOControlPtr;
  852.     int             numFailed;
  853. {
  854.     RaidBlockRequest    *failedReqPtr;
  855.     failedReqPtr = stripeIOControlPtr->reqControlPtr->failedReqPtr;
  856.  
  857.     switch (numFailed) {
  858.     case 0:
  859. #ifndef NODATA
  860.     bzero(failedReqPtr->devReq.buffer, failedReqPtr->devReq.bufferLen);
  861. #endif
  862.     Raid_XorRangeRequests(stripeIOControlPtr->reqControlPtr,
  863.         stripeIOControlPtr->raidPtr, failedReqPtr->devReq.buffer,
  864.         (int) failedReqPtr->devReq.startAddress,
  865.         failedReqPtr->devReq.bufferLen);
  866.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  867.     break;
  868.     default:
  869.     stripeIODoneProc(stripeIOControlPtr, numFailed);
  870.     break;
  871.     }
  872. }
  873.  
  874.  
  875. /*
  876.  *----------------------------------------------------------------------
  877.  *
  878.  * InitiateSingleStripeIO --
  879.  *
  880.  *    Initiates a single stripe IO request.
  881.  *    Locks stripe, does IO and then unlocks the stripe in order to
  882.  *    guarantee the consistency of parity.  (The unlocking is done in the
  883.  *    associated callback procedure.)
  884.  *    Calls doneProc with clientData, status and the amount transferreed
  885.  *    as arguments when the IO is completed.
  886.  *
  887.  * Results:
  888.  *    None.
  889.  *
  890.  * Side effects:
  891.  *    The IO operation.
  892.  *    Locks stripe.
  893.  *
  894.  *----------------------------------------------------------------------
  895.  */
  896.  
  897. static void stripeIODoneProc();
  898.  
  899. static void 
  900. InitiateSingleStripeIO(raidPtr, operation, firstSector, nthSector,
  901.                 buffer, doneProc, clientData, ctrlData)
  902.     Raid       *raidPtr;
  903.     int        operation;
  904.     unsigned     firstSector, nthSector;
  905.     Address      buffer;
  906.     void      (*doneProc)();
  907.     ClientData    clientData;
  908.     int         ctrlData;
  909. {
  910.     RaidStripeIOControl    *stripeIOControlPtr;
  911.     stripeIOControlPtr = Raid_MakeStripeIOControl(raidPtr, operation,
  912.         firstSector, nthSector, buffer, doneProc, clientData, ctrlData);
  913.  
  914.     switch (stripeIOControlPtr->operation) {
  915.     case FS_READ:
  916.     Raid_SLockStripe(raidPtr,
  917.         SectorToStripeID(raidPtr, stripeIOControlPtr->firstSector));
  918.     InitiateStripeRead(stripeIOControlPtr);
  919.     break;
  920.     case FS_WRITE:
  921.     Raid_XLockStripe(raidPtr,
  922.         SectorToStripeID(raidPtr, stripeIOControlPtr->firstSector));
  923.     InitiateStripeWrite(stripeIOControlPtr);
  924.     break;
  925.     }
  926. }
  927.  
  928.  
  929. /*
  930.  *----------------------------------------------------------------------
  931.  *
  932.  * stripeIODoneProc --
  933.  *
  934.  *    Callback procedure for InitiateSingleStripeIO.
  935.  *
  936.  * Results:
  937.  *    None.
  938.  *
  939.  * Side effects:
  940.  *    Unlocks stripe.
  941.  *
  942.  *----------------------------------------------------------------------
  943.  */
  944.  
  945. static void
  946. stripeIODoneProc(stripeIOControlPtr, numFailed)
  947.     RaidStripeIOControl    *stripeIOControlPtr;
  948.     int             numFailed;
  949. {
  950.     if (stripeIOControlPtr->operation == FS_WRITE) {
  951.     Raid_XUnlockStripe(stripeIOControlPtr->raidPtr,
  952.         SectorToStripeID(stripeIOControlPtr->raidPtr,
  953.         stripeIOControlPtr->firstSector));
  954.     } else {
  955.     Raid_SUnlockStripe(stripeIOControlPtr->raidPtr,
  956.         SectorToStripeID(stripeIOControlPtr->raidPtr,
  957.         stripeIOControlPtr->firstSector));
  958.     }
  959.     if (numFailed == 0) {
  960.         stripeIOControlPtr->doneProc(stripeIOControlPtr->clientData, SUCCESS, 
  961.         SectorToByte(stripeIOControlPtr->raidPtr,
  962.             stripeIOControlPtr->nthSector -
  963.             stripeIOControlPtr->firstSector));
  964.     } else {
  965.         stripeIOControlPtr->doneProc(stripeIOControlPtr->clientData, FAILURE,0);
  966.     }
  967.     Raid_FreeStripeIOControl(stripeIOControlPtr);
  968. }
  969.  
  970.  
  971. /*
  972.  *----------------------------------------------------------------------
  973.  *
  974.  * Raid_InitiateStripeIOs --
  975.  *
  976.  *    Breaks IO requests into single stripe requests.
  977.  *    Calls doneProc with clientData, status and the amount transferreed
  978.  *    as arguments when the IO is completed.
  979.  *
  980.  * Results:
  981.  *    The return code from queuing the I/O operation.
  982.  *
  983.  * Side effects:
  984.  *    The IO operation.
  985.  *
  986.  *----------------------------------------------------------------------
  987.  */
  988.  
  989. static void singleStripeIODoneProc();
  990.  
  991. void 
  992. Raid_InitiateStripeIOs(raidPtr, operation, firstSector, nthSector,
  993.                 buffer, doneProc, clientData, ctrlData)
  994.     Raid       *raidPtr;
  995.     int        operation;
  996.     unsigned     firstSector, nthSector;
  997.     Address      buffer;
  998.     void      (*doneProc)();
  999.     ClientData    clientData;
  1000.     int         ctrlData;
  1001. {
  1002.     RaidIOControl       *IOControlPtr;
  1003.     int            numSectorsToTransfer;
  1004.     unsigned            currentSector;
  1005.  
  1006.     /*
  1007.      * Break up IO request into stripe requests.
  1008.      */
  1009.     Raid_BeginUse(raidPtr);
  1010.     IOControlPtr = Raid_MakeIOControl(doneProc, clientData);
  1011.     IOControlPtr->raidPtr = raidPtr;
  1012.     IOControlPtr->numIO++;
  1013.     currentSector = firstSector;
  1014.     while ( currentSector < nthSector ) {
  1015.         numSectorsToTransfer = MIN( raidPtr->dataSectorsPerStripe -
  1016.                 currentSector%raidPtr->dataSectorsPerStripe,
  1017.                 nthSector - currentSector );
  1018.  
  1019.         MASTER_LOCK(&IOControlPtr->mutex);
  1020.     IOControlPtr->numIO++;
  1021.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1022.  
  1023.         InitiateSingleStripeIO(raidPtr, operation,
  1024.                  currentSector, currentSector+numSectorsToTransfer, buffer,
  1025.                  singleStripeIODoneProc, (ClientData) IOControlPtr,
  1026.                  ctrlData);
  1027.  
  1028.         currentSector += numSectorsToTransfer;
  1029.     buffer += SectorToByte(raidPtr, numSectorsToTransfer);
  1030.     }
  1031.  
  1032.     MASTER_LOCK(&IOControlPtr->mutex);
  1033.     IOControlPtr->numIO--;
  1034.     if (IOControlPtr->numIO == 0) {
  1035.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1036.         IOControlPtr->doneProc(IOControlPtr->clientData,
  1037.         IOControlPtr->status, IOControlPtr->amountTransferred);
  1038.     Raid_FreeIOControl(IOControlPtr);
  1039.     Raid_EndUse(IOControlPtr->raidPtr);
  1040.     } else {
  1041.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1042.     }
  1043. }
  1044.  
  1045.  
  1046. /*
  1047.  *----------------------------------------------------------------------
  1048.  *
  1049.  * singleStripeIODoneProc --
  1050.  *
  1051.  *    Callback procedure for Raid_InitiateStripeIOs.
  1052.  *
  1053.  * Results:
  1054.  *    None.
  1055.  *
  1056.  * Side effects:
  1057.  *    None.
  1058.  *
  1059.  *----------------------------------------------------------------------
  1060.  */
  1061.  
  1062. static void
  1063. singleStripeIODoneProc(IOControlPtr, status, amountTransferred)
  1064.     RaidIOControl    *IOControlPtr;
  1065.     ReturnStatus       status;
  1066.     int               amountTransferred;
  1067. {
  1068.     MASTER_LOCK(&IOControlPtr->mutex);
  1069.     IOControlPtr->amountTransferred += amountTransferred;
  1070.  
  1071.     /*
  1072.      * A Raid IO operation fails if any of the component operations fail.
  1073.      * Therefore, don't overwrite status if a previous operation has failed.
  1074.      */
  1075.     if (IOControlPtr->status == SUCCESS) {
  1076.         IOControlPtr->status = status;
  1077.     }
  1078.  
  1079.     /*
  1080.      * Check if all component IO's done.
  1081.      */
  1082.     IOControlPtr->numIO--;
  1083.     if (IOControlPtr->numIO == 0) {
  1084.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1085.         IOControlPtr->doneProc(IOControlPtr->clientData,
  1086.         IOControlPtr->status, IOControlPtr->amountTransferred);
  1087.     Raid_FreeIOControl(IOControlPtr);
  1088.     Raid_EndUse(IOControlPtr->raidPtr);
  1089.     } else {
  1090.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1091.     }
  1092. }
  1093.  
  1094.  
  1095. /*
  1096.  *----------------------------------------------------------------------
  1097.  *
  1098.  * Raid_InitiateSimpleStripeIOs --
  1099.  *
  1100.  *    Breaks up IO requests in stripes and then initiates them.
  1101.  *    This procedure is used when the RAID device is configured without
  1102.  *    parity.
  1103.  *
  1104.  * Results:
  1105.  *    None.
  1106.  *
  1107.  * Side effects:
  1108.  *    The IO operation.
  1109.  *
  1110.  *----------------------------------------------------------------------
  1111.  */
  1112.  
  1113. static void simpleStripeIODoneProc();
  1114.  
  1115. void 
  1116. Raid_InitiateSimpleStripeIOs(raidPtr, operation, firstSector, nthSector,
  1117.                 buffer, doneProc, clientData, ctrlData)
  1118.     Raid       *raidPtr;
  1119.     int        operation;
  1120.     unsigned     firstSector, nthSector;
  1121.     Address      buffer;
  1122.     void      (*doneProc)();
  1123.     ClientData    clientData;
  1124.     int         ctrlData;
  1125. {
  1126.     RaidIOControl       *IOControlPtr;
  1127.     DevBlockDeviceRequest *devReqPtr;
  1128.     int            numSectorsToTransfer;
  1129.     unsigned            currentSector;
  1130.     unsigned            diskSector;
  1131.     int               col, row;
  1132.  
  1133.     /*
  1134.      * Break up entire IO request into stripe units.
  1135.      */
  1136.     IOControlPtr = Raid_MakeIOControl(doneProc, clientData);
  1137.     IOControlPtr->numIO++;
  1138.     currentSector = firstSector;
  1139.     while ( currentSector < nthSector ) {
  1140.         numSectorsToTransfer = MIN( raidPtr->sectorsPerStripeUnit -
  1141.                 currentSector%raidPtr->sectorsPerStripeUnit,
  1142.                 nthSector - currentSector );
  1143.     Raid_MapSector(raidPtr, currentSector, &col, &row, &diskSector);
  1144.     devReqPtr = Raid_MakeBlockDeviceRequest(raidPtr, operation,
  1145.         diskSector, numSectorsToTransfer, buffer,
  1146.         simpleStripeIODoneProc, (ClientData) IOControlPtr, ctrlData);
  1147.  
  1148.         MASTER_LOCK(&IOControlPtr->mutex);
  1149.     IOControlPtr->numIO++;
  1150.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1151.  
  1152.         (void) Dev_BlockDeviceIO(raidPtr->disk[col][row]->handlePtr, devReqPtr);
  1153.  
  1154.         currentSector += numSectorsToTransfer;
  1155.     buffer += SectorToByte(raidPtr, numSectorsToTransfer);
  1156.     }
  1157.  
  1158.     MASTER_LOCK(&IOControlPtr->mutex);
  1159.     IOControlPtr->numIO--;
  1160.     if (IOControlPtr->numIO == 0) {
  1161.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1162.         IOControlPtr->doneProc(IOControlPtr->clientData,
  1163.         IOControlPtr->status, IOControlPtr->amountTransferred);
  1164.     Raid_FreeIOControl(IOControlPtr);
  1165.     } else {
  1166.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1167.     }
  1168. }
  1169.  
  1170.  
  1171. /*
  1172.  *----------------------------------------------------------------------
  1173.  *
  1174.  * simpleStripeIODoneProc --
  1175.  *
  1176.  *    Callback procedure for Raid_InitiateSimpleStripeIOs.
  1177.  *
  1178.  * Results:
  1179.  *    None.
  1180.  *
  1181.  * Side effects:
  1182.  *    Reports errors.
  1183.  *    Calls callback procedure.
  1184.  *
  1185.  *----------------------------------------------------------------------
  1186.  */
  1187.  
  1188. static void
  1189. simpleStripeIODoneProc(devReqPtr, status, amountTransferred)
  1190.     DevBlockDeviceRequest *devReqPtr;
  1191.     ReturnStatus       status;
  1192.     int               amountTransferred;
  1193. {
  1194.     RaidIOControl    *IOControlPtr = (RaidIOControl *) devReqPtr->clientData;
  1195.  
  1196.     Raid_FreeBlockDeviceRequest(devReqPtr);
  1197.  
  1198.     MASTER_LOCK(&IOControlPtr->mutex);
  1199.     IOControlPtr->amountTransferred += amountTransferred;
  1200.  
  1201.     /*
  1202.      * A Raid IO operation fails if any of the component operations fail.
  1203.      * Therefore, don't overwrite status if a previous operation has failed.
  1204.      */
  1205.     if (IOControlPtr->status == SUCCESS) {
  1206.         IOControlPtr->status = status;
  1207.     }
  1208.  
  1209.     /*
  1210.      * Check if all component IO's done.
  1211.      */
  1212.     IOControlPtr->numIO--;
  1213.     if (IOControlPtr->numIO == 0) {
  1214.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1215.         IOControlPtr->doneProc(IOControlPtr->clientData,
  1216.         IOControlPtr->status, IOControlPtr->amountTransferred);
  1217.     Raid_FreeIOControl(IOControlPtr);
  1218.     } else {
  1219.         MASTER_UNLOCK(&IOControlPtr->mutex);
  1220.     }
  1221. }
  1222.